package managers;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import javax.swing.ImageIcon;

import managers.socialNetworkManagers.CacheManager;
import managers.socialNetworkManagers.SocialNetworkManager;
import spotGUI.eventsGUI.Birthday;
import spotGUI.eventsGUI.EventsFrame;
import utils.ImageUtils;
import utils.StackTracePrinter;
import elements.Event;

public class EventsManager {

	public static final int NO_EVENTS = -1;
	
	
	private static EventsManager sharedInstance = new EventsManager();
	
	private EventsFrame frame;
	private int userId;

	private EventsManager () {
	}
	
	public void initialize (int userId) {
		
		frame = new EventsFrame(this);
		this.userId = userId;
		
		try {
			updateBirthdays(DBManager.getConnection());
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			StackTracePrinter.print(e);
		}
	}


	public void retrieveEvents (Date from, Date to, Connection conn) throws SQLException, IllegalArgumentException {
		if (from == null && to == null) {
			throw new IllegalArgumentException("FROM date is null.");
		}
		Calendar cal = Calendar.getInstance();
		
		
		frame.removeEvents();
		String query = "select eventid, name, date, target from spotmessenger.event";
		if (from != null && to != null) {
			if (from.compareTo(to) > 0) {
				throw new IllegalArgumentException("FROM date is greater than TO date.");
			}
			cal.setTime(to);
			cal.set(Calendar.HOUR_OF_DAY, 23);
			cal.set(Calendar.MINUTE, 59);
			cal.set(Calendar.SECOND, 59);
			query += " where date <= '"+new Timestamp(cal.getTime().getTime())+"' and date >= '"+new Timestamp(from.getTime())+"'";
		} else if (from != null && to == null) {
			query += " where date >= '"+new Timestamp(from.getTime())+"'";
		} else {
			query += " where date <= '"+new Timestamp(cal.getTime().getTime())+"'";
			cal.setTime(to);
			cal.set(Calendar.HOUR_OF_DAY, 23);
			cal.set(Calendar.MINUTE, 59);
			cal.set(Calendar.SECOND, 59);
		}
		doUpdate(query, conn);
	}

	public void setParticipant (int userId, int eventId, Connection conn) throws SQLException {
		Statement stmt = conn.createStatement();
		String query = "INSERT INTO spotmessenger.participants VALUES ("+eventId+" , "+userId+")";
		stmt.executeUpdate(query);
		DBManager.closeResources(stmt, null);
	}

	public void updateEventList (Connection conn) throws SQLException {
		Calendar currentDate = Calendar.getInstance();
		String currentTime = new Timestamp(currentDate.getTimeInMillis()).toString();
		String nextMonth = getNextMonth(currentDate);
		String query = "select eventid, name, date, target from spotmessenger.event where date <= '"+nextMonth+
				"' and date >= '"+currentTime+"'";
		doUpdate(query, conn);
	}


	private String getNextMonth(Calendar cal) {
		cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, 1);
		return new Timestamp(cal.getTimeInMillis()).toString();
	}
	
	private void doUpdate (String query, Connection conn) throws SQLException {
		frame.resetEventsBox();
		Statement stmt = conn.createStatement();
		stmt.executeQuery(query);
		ResultSet rs = stmt.executeQuery(query);
		frame.removeEvents();
		while (rs.next()) {
			frame.addEvent(new Event(rs.getInt(1), rs.getString(2), rs.getTimestamp(3), rs.getString(4)));
		}
		if (frame.getEventList().getModel().getSize() == 0) {
			Event noEvents = new Event(EventsManager.NO_EVENTS, "Nessun evento.", new Timestamp(new Date().getTime()), null);
			noEvents.photo = new ImageIcon(EventsManager.class.getResource("/images/Icons/128x128/calendar_delete.png"));
			frame.addEvent(noEvents);
		}
		DBManager.closeResources(stmt, rs);
	}


	public EventsFrame getFrame() {
		return frame;
	}
	
	public void setFrameVisible () {
			frame.setVisible(true);
			try {
				updateEventList(DBManager.getConnection());
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				StackTracePrinter.print(e);
			}
			frame.getEventList().setSelectedIndex(0);
	}


	public void retrieveCompleteEvent(Event event, Connection conn) throws SQLException, IOException {
		Statement stmt = conn.createStatement();
		event.photo = CacheManager.retrieveImage(CacheManager.formatEventName(event.eventId), null);
		String query;
		ResultSet rs;
		if (event.photo == null) {
			query = "select body, photo from spotmessenger.event where eventid = "+event.eventId;
			rs = stmt.executeQuery(query);
			rs.next();
			event.body = rs.getString(1);
			event.photo = ImageUtils.bytesToImage(rs.getBytes(2), "/images/Icons/128x128/calendar_blank.png");
			if (rs.getBytes(2) != null)
				CacheManager.saveImage(rs.getBytes(2), CacheManager.formatEventName(event.eventId));
		} else {
			query = "select body from spotmessenger.event where eventid = "+event.eventId;
			rs = stmt.executeQuery(query);
			rs.next();
			event.body = rs.getString(1);
		}
		DBManager.closeResources(stmt, rs);

		Statement stmt2 = conn.createStatement();
		String query2 = "select userid from spotmessenger.participants where eventid = "+event.eventId;
		ResultSet rs2 = stmt2.executeQuery(query2);
		ArrayList<Integer> participants = new ArrayList<Integer>();
		while (rs2.next()) {
			participants.add(rs2.getInt(1));
		}
		DBManager.closeResources(stmt2, rs2);
		event.participants = participants;
	}


	public void updateBirthdays (Connection conn) throws SQLException {
		Calendar currentDate = Calendar.getInstance();
		
		Statement stmt = conn.createStatement();
		String query = "select P.id, P.birthdate from spotmessenger.personal_data P " +
				"where ((MONTH(P.birthdate) = "+ (currentDate.get(Calendar.MONTH)+1) + " and DAY(P.birthdate) >= "+currentDate.get(Calendar.DAY_OF_MONTH)+
				") or (MONTH(P.birthdate) = "+ (currentDate.get(Calendar.MONTH)+1) +"+1 and DAY(P.birthdate) <= "+currentDate.get(Calendar.DAY_OF_MONTH)+")) " +
						"order by MONTH(birthdate), DAY(birthdate)";
		ResultSet rs = stmt.executeQuery(query);
		while (rs.next()) {
			frame.addBirthday(new Birthday(rs.getTimestamp(2), SocialNetworkManager.getSharedInstance().getUser(rs.getInt(1))));
		}
		DBManager.closeResources(stmt, rs);
		if (frame.getListBirthday().getModel().getSize() == 0) {
			frame.addBirthday(new Birthday(null, null));
		}
	}


	public int getUserId() {
		return userId;
	}


	public static EventsManager getSharedInstance() {
		return sharedInstance;
	}


}
